package com.ji;

import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Arrays;

/**
 * @Author:JI
 * @Date:2025/6/12-10:00
 * @Decsription:com.ji
 */


public class MainFrame extends JFrame {
    public static final String IMAGE_PATH = "stonemaze/src/image/";

    private int[][] imageData = new int[][]{
            {1, 2, 3, 4},
            {5, 6, 7, 8},
            {9, 10, 11, 12},
            {13, 14, 15, 0}
    };

    private int[][] winData = new int[][]{  // 定义一个二维数组，用来存储最终游戏成功的数据顺序。
            {1, 2, 3, 4},
            {5, 6, 7, 8},
            {9, 10, 11, 12},
            {13, 14, 15, 0}
    };


    private int row;  // 定义两个整数变量记录当前空白色块的位置。
    private int col;
    private int count;  // 定义一个计数变量，记录步数。


    // 无参构造器，调用初始化方法
    public MainFrame() {
        initFrame();
        initMenu();
        initRandomArray();
        initImage();
        initKeyPressEvent();
        this.setVisible(true);
    }

    // 判断游戏二维数组和赢了之后的二维数组的内容是否一样
    public boolean isWin() {
        if ( Arrays.deepEquals(imageData, winData)) {
            return true;
        }
        return false;
    }

    // 监听键盘事件 方法：调用switchAndMove方法
    private void initKeyPressEvent() {
        this.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                int keyCode = e.getKeyCode();
                switch (keyCode) {
                    case KeyEvent.VK_UP:
                        switchAndMove(Direction.UP);  // 用枚举类做判断的常量
                        break;
                    case KeyEvent.VK_DOWN:
                        switchAndMove(Direction.DOWN);
                        break;
                    case KeyEvent.VK_LEFT:
                        switchAndMove(Direction.LEFT);
                        break;
                    case KeyEvent.VK_RIGHT:
                        switchAndMove(Direction.RIGHT);
                        break;
                }
            }
        });
    }

    // 控制数据交换，和图片移动。
    private void switchAndMove(Direction d) {
        // 判断图片的方向，再控制图片移动
        switch (d) {
            case UP:  // 上交换的条件是行必须 < 3，然后才开始交换.
                if (row < 3) {
                    int temp = imageData[row][col];
                    imageData[row][col] = imageData[row + 1][col];
                    imageData[row + 1][col] = temp;
                    row++;
                    count++;
                }
                break;
            case DOWN:  // 下交换的条件是行必须 > 0，然后才开始交换.
                if  (row > 0) {
                    int temp = imageData[row][col];
                    imageData[row][col] = imageData[row - 1][col];
                    imageData[row - 1][col] = temp;
                    row--;
                    count++;
                }
                break;
            case LEFT:  // 左交换的条件是行必须 < 3，然后才开始交换.
                if (col < 3) {
                    int temp = imageData[row][col];
                    imageData[row][col] = imageData[row][col + 1];
                    imageData[row][col + 1] = temp;
                    col++;
                    count++;
                }
                break;
            case RIGHT:  // 右交换的条件是行必须 > 0，然后才开始交换.
                if  (col > 0) {
                    int temp = imageData[row][col];
                    imageData[row][col] = imageData[row][col - 1];
                    imageData[row][col - 1] = temp;
                    col--;
                    count++;
                }
                break;
        }
        // 重新刷新界面！！！
        this.initImage();
    }

    // 随机生成图片 数组 方法
    private void initRandomArray() {
        for (int i = 0; i < imageData.length; i++) {
            for (int j = 0; j < imageData[i].length; j++) {
                int i1 = (int) (Math.random() * imageData.length);
                int j1 = (int) (Math.random() * imageData.length);
                int i2 = (int) (Math.random() * imageData.length);
                int j2 = (int) (Math.random() * imageData.length);

                int temp = imageData[i1][j1];
                imageData[i1][j1] = imageData[i2][j2];
                imageData[i2][j2] = temp;
            }
        }

        // 找到空白色块的位置
        OUT:
        for (int i = 0; i < imageData.length; i++) {
            for (int j = 0; j < imageData[i].length; j++) {
                if (imageData[i][j] == 0) {
                    row = i;
                    col = j;
                    break OUT;
                }
            }
        }
    }

    // 初始化图片 方法
    private void initImage() {
        // 先清空窗口上的全部图层
        this.getContentPane().removeAll();  // 不会自动触发重绘，需要手动调用repaint()方法。

        // 显示步数
        JLabel countLabel = new JLabel("当前移动：" + count);
        countLabel.setBounds(40, 33, 150, 20);
        countLabel.setFont(new Font("幼圆", Font.BOLD, 15));
        countLabel.setForeground(Color.ORANGE);
        this.add(countLabel);

        // 判断游戏是否胜利，胜利->显示胜利的图片
        if (isWin()) {
            JLabel jl = new JLabel(new ImageIcon(IMAGE_PATH + "win.png"));
            jl.setBounds(124, 230, 266, 88);
            this.add(jl);
        }

        // 设置图片标签的位置
        for (int i = 0; i < imageData.length; i++) {
            for (int j = 0; j < imageData[i].length; j++) {
                int number = imageData[i][j];
                JLabel label = new JLabel();
                // 创建图片对象,加入标签中
                label.setIcon(new ImageIcon((IMAGE_PATH + number + ".png")));
                label.setBounds(35 + j * 100, 71 + i * 100, 100, 100);
                this.add(label);
            }
        }

        // 设置窗口的背景图片
        JLabel backgroundLabel = new JLabel(new ImageIcon(IMAGE_PATH + "background.png"));
        backgroundLabel.setBounds(9, 12, 450, 484);
        this.add(backgroundLabel);

        // 刷新界面
        this.repaint();
    }

    // 初始化菜单 方法
    private void initMenu() {
        JMenuBar menuBar = new JMenuBar();
        JMenu menu = new JMenu("系统");
        JMenuItem restartItem = new JMenuItem("重启游戏");
        JMenuItem exitItem = new JMenuItem("退出程序");

        restartItem.addActionListener(e -> {
            // 重启游戏
            System.out.println("重启游戏");
            count = 0;
            initRandomArray();
            initImage();

        });

        exitItem.addActionListener(e -> {
            // 退出程序
            System.out.println("退出程序");
            this.dispose();
        });

        menu.add(restartItem);
        menu.add(exitItem);
        menuBar.add(menu);
        this.setJMenuBar(menuBar);
    }

    // 初始化窗体 方法
    private void initFrame() {
        this.setTitle("石子迷阵 v1.0");
        this.setSize(480, 580);
        this.setLocationRelativeTo(null);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setLayout(null);
    }

}
